Java读取文件头部获得文件类型的工具类

原因

为什么不直接使用文件后缀判断文件类型,而要通过读取文件头部获得文件类型呢?
原因是,处于安全考虑,部分木马程序是通过改变后缀来伪装为文件,上传到服务器,在服务器中作为可执行文件,对服务器进行攻击,通过文件头部文件获取真实文件类型,来限制此类病毒文件的上传来保护服务

##工具类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
 
import java.io.File;

import java.io.FileInputStream;

import java.util.HashMap;

import java.util.Iterator;

import java.util.Map;

import java.util.Map.Entry;

/***********************************************************************

*

* Description: 主要用于判断文件的类型

*

***********************************************************************/

class FileTools {
public final static Map FILE_TYPE_MAP = new HashMap();

/*-----------------------------目前可以识别的类型----------------------------*/

private static void getAllFileType() {
FILE_TYPE_MAP.put("jpg", "FFD8FF"); //JPEG

FILE_TYPE_MAP.put("png", "89504E47"); //PNG

FILE_TYPE_MAP.put("gif", "47494638"); //GIF

FILE_TYPE_MAP.put("tif", "49492A00"); //TIFF

FILE_TYPE_MAP.put("bmp", "424D"); //Windows Bitmap

FILE_TYPE_MAP.put("dwg", "41433130"); //CAD

FILE_TYPE_MAP.put("html", "68746D6C3E"); //HTML

FILE_TYPE_MAP.put("rtf", "7B5C727466"); //Rich Text Format

FILE_TYPE_MAP.put("xml", "3C3F786D6C");

FILE_TYPE_MAP.put("zip", "504B0304");

FILE_TYPE_MAP.put("rar", "52617221");

FILE_TYPE_MAP.put("psd", "38425053"); //PhotoShop

FILE_TYPE_MAP.put("eml", "44656C69766572792D646174653A"); //Email [thorough only]

FILE_TYPE_MAP.put("dbx", "CFAD12FEC5FD746F"); //Outlook Express

FILE_TYPE_MAP.put("pst", "2142444E"); //Outlook

FILE_TYPE_MAP.put("office", "D0CF11E0"); //office类型,包括doc、xls和ppt

FILE_TYPE_MAP.put("mdb", "000100005374616E64617264204A"); //MS Access

FILE_TYPE_MAP.put("wpd", "FF575043"); //WordPerfect

FILE_TYPE_MAP.put("eps", "252150532D41646F6265");

FILE_TYPE_MAP.put("ps", "252150532D41646F6265");

FILE_TYPE_MAP.put("pdf", "255044462D312E"); //Adobe Acrobat

FILE_TYPE_MAP.put("qdf", "AC9EBD8F"); //Quicken

FILE_TYPE_MAP.put("pwl", "E3828596"); //Windows Password

FILE_TYPE_MAP.put("wav", "57415645"); //Wave

FILE_TYPE_MAP.put("avi", "41564920");

FILE_TYPE_MAP.put("ram", "2E7261FD"); //Real Audio

FILE_TYPE_MAP.put("rm", "2E524D46"); //Real Media

FILE_TYPE_MAP.put("mpg", "000001BA"); //

FILE_TYPE_MAP.put("mov", "6D6F6F76"); //Quicktime

FILE_TYPE_MAP.put("asf", "3026B2758E66CF11"); //Windows Media

FILE_TYPE_MAP.put("mid", "4D546864"); //MIDI (mid)

}

/**
* 通过读取文件头部获得文件类型
*
* @param file
* @return 文件类型
*/

public static String getFileType(File file) {
getAllFileType();

String fileExtendName = null;

FileInputStream is;

try {
is = new FileInputStream(file);

byte[] b = new byte[16];

is.read(b, 0, b.length);

String filetypeHex = String.valueOf(bytesToHexString(b));

Iterator<Entry> entryiterator = FILE_TYPE_MAP.entrySet().iterator();

while (entryiterator.hasNext()) {
Entry entry = entryiterator.next();

String fileTypeHexValue = (String) entry.getValue();

if (filetypeHex.toUpperCase().startsWith(fileTypeHexValue)) {
fileExtendName = (String) entry.getKey();

if (fileExtendName.equals("office")) {
fileExtendName = getOfficeFileType(is);

}

is.close();

break;

}

}

// 如果不是上述类型,则判断扩展名

if (fileExtendName == null) {
String fileName = file.getName();

// 如果无扩展名,则直接返回空串

if (-1 == fileName.indexOf(".")) {
return "";

}

// 如果有扩展名,则返回扩展名

return fileName.substring(fileName.indexOf(".") + 1);

}

is.close();

return fileExtendName;

} catch (Exception exception) {
return "";

}

}

/**
* 判断office文件的具体类型
*
* @param fileInputStream
* @return office文件具体类型
*/

private static String getOfficeFileType(FileInputStream fileInputStream) {
String officeFileType = "doc";

byte[] b = new byte[512];

try {
fileInputStream.read(b, 0, b.length);

String filetypeHex = String.valueOf(bytesToHexString(b));

String flagString = filetypeHex.substring(992, filetypeHex.length());

if (flagString.toLowerCase().startsWith("eca5c")) {
officeFileType = "doc";

} else if (flagString.toLowerCase().startsWith("fdffffff09")) {
officeFileType = "xls";

} else if (flagString.toLowerCase().startsWith("09081000000")) {
officeFileType = "xls";

} else {
officeFileType = "ppt";

}

return officeFileType;

} catch (Exception e) {
e.printStackTrace();
return "";
}

}

/**
* 获得文件头部字符串
*
* @param src
* @return
*/

private static String bytesToHexString(byte[] src) {
StringBuilder stringBuilder = new StringBuilder();

if (src == null || src.length <= 0) {
return null;

}

for (int i = 0; i < src.length; i++) {
int v = src[i] & 0xFF;

String hv = Integer.toHexString(v);

if (hv.length() < 2) {
stringBuilder.append(0);

}

stringBuilder.append(hv);

}

return stringBuilder.toString();

}

public static void main(String[] args) {
File file = new File("E:/济指办发〔2022〕203号关于加强改进重点区域管理服务工作的通知.word");
String testfileName = getFileType(file);
System.out.println("真实:"+testfileName);
FileInputStream is;

try {
is = new FileInputStream(file);

byte[] b = new byte[16];

is.read(b, 0, b.length);

String filetypeHex = String.valueOf(bytesToHexString(b));
System.out.println("前16位码:"+filetypeHex);

String fileName = file.getName();

System.out.println("外部编译:"+fileName.substring(fileName.indexOf(".") + 1));

} catch (Exception e) {
e.printStackTrace();

}

}
}

一辈子很短,努力的做好两件事就好;
第一件事是热爱生活,好好的去爱身边的人;
第二件事是努力学习,在工作中取得不一样的成绩,实现自己的价值,而不是仅仅为了赚钱;

继开 wechat
欢迎加我的微信,共同交流技术